/**
 * Copyright (c) 2020 Coder League
 * All rights reserved.
 *
 * File：HttpUtil.java
 * History:
 *         2020年12月23日: Initially created, Chrise.
 */
package club.coderleague.cfss.util;

import java.io.File;
import java.io.FileInputStream;
import java.security.KeyStore;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import javax.net.ssl.SSLContext;

import org.apache.http.HttpEntity;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.EntityBuilder;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.util.EntityUtils;

/**
 * HTTP工具。
 * @author Chrise
 */
public class HttpUtil {
	private static final int CONNECT_TIMEOUT = 10000;
	private static final int REQUEST_TIMEOUT = 10000;
	private static final int SOCKET_TIMEOUT = 30000;
	private static final String CONTENT_ENCODING = "UTF-8";
	
	/**
	 * GET请求。
	 * @author Chrise 2020年12月23日
	 * @param url 请求地址。
	 * @return 结果字符串。
	 * @throws Exception 请求异常。
	 */
	public static String get(String url) throws Exception {
		String result = null;
		CloseableHttpClient client = null;
		CloseableHttpResponse response = null;
		
		try {
			// 创建请求配置
			RequestConfig config = RequestConfig.custom()
												.setConnectTimeout(CONNECT_TIMEOUT)
												.setConnectionRequestTimeout(REQUEST_TIMEOUT)
												.setSocketTimeout(SOCKET_TIMEOUT)
												.setRedirectsEnabled(true)
												.build();
			
			// 创建GET对象
			HttpGet get = new HttpGet(url);
			get.setConfig(config);
			
			// 执行请求并读取响应结果
			client = HttpClients.createDefault();
			response = client.execute(get);
			if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
				result = EntityUtils.toString(response.getEntity());
			}
		} finally {
			if (response != null) response.close();
			if (client != null) client.close();
		}
		
		return result;
	}
	
	/**
	 * POST请求。
	 * @author Chrise 2020年12月23日
	 * @param url 请求地址。
	 * @param data 请求数据。
	 * @return 字符串结果。
	 * @throws Exception 请求异常。
	 */
	public static String post(String url, String data) throws Exception {
		String result = null;
		CloseableHttpClient client = null;
		CloseableHttpResponse response = null;
		
		try {
			// 创建请求配置
			RequestConfig config = RequestConfig.custom()
												.setConnectTimeout(CONNECT_TIMEOUT)
												.setConnectionRequestTimeout(REQUEST_TIMEOUT)
												.setSocketTimeout(SOCKET_TIMEOUT)
												.setRedirectsEnabled(true)
												.build();
			
			// 创建请求实体
			HttpEntity entity = EntityBuilder.create()
											 .setContentEncoding(CONTENT_ENCODING)
											 .setBinary(data.getBytes(CONTENT_ENCODING))
											 .build();
			
			// 创建POST请求
			HttpPost post = new HttpPost(url);
			post.setConfig(config);
			post.setEntity(entity);
			
			// 执行请求并读取响应结果
			client = HttpClients.createDefault();
			response = client.execute(post);
			if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
				result = EntityUtils.toString(response.getEntity());
			}
		} finally {
			if (response != null) response.close();
			if (client != null) client.close();
		}
		
		return result;
	}
	
	/**
	 * POST请求。
	 * @author Chrise 2020年12月23日
	 * @param url 请求地址。
	 * @param data 请求数据。
	 * @return 字符串结果。
	 * @throws Exception 请求异常。
	 */
	public static String post(String url, Map<String, String> data) throws Exception {
		String result = null;
		CloseableHttpClient client = null;
		CloseableHttpResponse response = null;
		
		try {
			// 创建请求配置
			RequestConfig config = RequestConfig.custom()
												.setConnectTimeout(CONNECT_TIMEOUT)
												.setConnectionRequestTimeout(REQUEST_TIMEOUT)
												.setSocketTimeout(SOCKET_TIMEOUT)
												.setRedirectsEnabled(true)
												.build();
			
			// 构造请求参数集合
			List<NameValuePair> params = new ArrayList<NameValuePair>();
			Iterator<Entry<String, String>> it = data.entrySet().iterator();
			while (it.hasNext()) {
				Entry<String, String> e = it.next();
				params.add(new BasicNameValuePair(e.getKey(), e.getValue()));
			}
			
			// 创建请求实体
			HttpEntity entity = EntityBuilder.create()
											 .setContentEncoding(CONTENT_ENCODING)
											 .setParameters(params)
											 .build();
			
			// 创建POST请求
			HttpPost post = new HttpPost(url);
			post.setConfig(config);
			post.setEntity(entity);
			
			// 执行请求并读取响应结果
			client = HttpClients.createDefault();
			response = client.execute(post);
			if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
				result = EntityUtils.toString(response.getEntity());
			}
		} finally {
			if (response != null) response.close();
			if (client != null) client.close();
		}
		
		return result;
	}
	
	/**
	 * POST请求。
	 * @author Chrise 2020年12月23日
	 * @param url 请求地址。
	 * @param data 请求数据。
	 * @param cert 证书路径。
	 * @param pwd 证书密码。
	 * @return 字符串结果。
	 * @throws Exception 请求异常。
	 */
	public static String post(String url, String data, String cert, String pwd) throws Exception {
		String result = null;
		FileInputStream stream = null;
		CloseableHttpClient client = null;
		CloseableHttpResponse response = null;
		
		try {
			// 创建请求配置
			RequestConfig config = RequestConfig.custom()
												.setConnectTimeout(CONNECT_TIMEOUT)
												.setConnectionRequestTimeout(REQUEST_TIMEOUT)
												.setSocketTimeout(SOCKET_TIMEOUT)
												.setRedirectsEnabled(true)
												.build();
			
			// 创建请求实体
			HttpEntity entity = EntityBuilder.create()
											 .setContentEncoding(CONTENT_ENCODING)
											 .setBinary(data.getBytes(CONTENT_ENCODING))
											 .build();
			
			// 创建POST请求
			HttpPost post = new HttpPost(url);
			post.setConfig(config);
			post.setEntity(entity);
			
			// 创建密码及证书文件流
			char[] password = pwd.toCharArray();
			stream = new FileInputStream(new File(cert));
			
			// 加载密钥
			KeyStore store = KeyStore.getInstance("PKCS12");
			store.load(stream, password);
			
			// 创建SSL上下文及连接工厂
			SSLContext context = SSLContexts.custom().loadKeyMaterial(store, password).build();
			SSLConnectionSocketFactory factory = new SSLConnectionSocketFactory(context);
			
			// 执行请求并读取响应结果
			client = HttpClients.custom().setSSLSocketFactory(factory).build();
			response = client.execute(post);
			if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
				result = EntityUtils.toString(response.getEntity());
			}
		} finally {
			if (stream != null) stream.close();
			if (response != null) response.close();
			if (client != null) client.close();
		}
		
		return result;
	}
}
